home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevpdff.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  25.5 KB  |  905 lines

  1. /* Copyright (C) 1999, 2000 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevpdff.c,v 1.8.2.1 2000/11/09 20:40:29 rayjj Exp $ */
  20. /* Font handling for pdfwrite driver. */
  21. #include "ctype_.h"
  22. #include "math_.h"
  23. #include "memory_.h"
  24. #include "string_.h"
  25. #include "gx.h"
  26. #include "gserrors.h"
  27. #include "gsmalloc.h"        /* for patching font memory */
  28. #include "gsmatrix.h"
  29. #include "gspath.h"
  30. #include "gsutil.h"        /* for bytes_compare */
  31. #include "gxfixed.h"        /* for gxfcache.h */
  32. #include "gxfont.h"
  33. #include "gxfcache.h"        /* for orig_fonts list */
  34. #include "gxpath.h"        /* for getting current point */
  35. #include "gdevpdfx.h"
  36. #include "gdevpdff.h"
  37. #include "gdevpdfo.h"
  38. #include "gdevpsf.h"
  39. #include "scommon.h"
  40.  
  41. /*
  42.  * In our quest to work around Acrobat Reader quirks, we're resorting to
  43.  * making all font names in the output unique by adding a suffix derived
  44.  * from the PDF object number.  We hope to get rid of this someday....
  45.  */
  46. static bool MAKE_FONT_NAMES_UNIQUE = true;
  47.  
  48. /* GC descriptors */
  49. public_st_pdf_font();
  50. public_st_pdf_char_proc();
  51. public_st_pdf_font_descriptor();
  52. private_st_pdf_encoding_element();
  53. private ENUM_PTRS_WITH(pdf_encoding_elt_enum_ptrs, pdf_encoding_element_t *pe) {
  54.     uint count = size / (uint)sizeof(*pe);
  55.  
  56.     if (index >= count)
  57.     return 0;
  58.     return ENUM_CONST_STRING(&pe[index].str);
  59. } ENUM_PTRS_END
  60. private RELOC_PTRS_WITH(pdf_encoding_elt_reloc_ptrs, pdf_encoding_element_t *pe)
  61.     uint count = size / (uint)sizeof(*pe);
  62.     uint i;
  63.  
  64.     for (i = 0; i < count; ++i)
  65.     RELOC_CONST_STRING_VAR(pe[i].str);
  66. RELOC_PTRS_END
  67.  
  68. /* Define the 14 standard built-in fonts. */
  69. const pdf_standard_font_t pdf_standard_fonts[] = {
  70. #define m(name, enc) {name, enc},
  71.     pdf_do_std_fonts(m)
  72. #undef m
  73.     {0}
  74. };
  75.  
  76. /* ---------------- Embedding status ---------------- */
  77.  
  78. /* Return the index of a standard font name, or -1 if missing. */
  79. int
  80. pdf_find_standard_font(const byte *str, uint size)
  81. {
  82.     const pdf_standard_font_t *ppsf;
  83.  
  84.     for (ppsf = pdf_standard_fonts; ppsf->fname; ++ppsf)
  85.     if (strlen(ppsf->fname) == size &&
  86.         !strncmp(ppsf->fname, (const char *)str, size)
  87.         )
  88.         return ppsf - pdf_standard_fonts;
  89.     return -1;
  90. }
  91.  
  92. /*
  93.  * If there is a standard font with the same appearance (CharStrings,
  94.  * Private, WeightVector) as the given font, set *psame to the mask of
  95.  * identical properties, and return the standard-font index; otherwise,
  96.  * set *psame to 0 and return -1.
  97.  */
  98. private int
  99. find_std_appearance(const gx_device_pdf *pdev, const gs_font_base *bfont,
  100.             int mask, int *psame)
  101. {
  102.     bool has_uid = uid_is_UniqueID(&bfont->UID) && bfont->UID.id != 0;
  103.     const pdf_std_font_t *psf = pdev->std_fonts;
  104.     int i;
  105.  
  106.     mask |= FONT_SAME_OUTLINES;
  107.     for (i = 0; i < PDF_NUM_STD_FONTS; ++psf, ++i) {
  108.     if (has_uid) {
  109.         if (!uid_equal(&bfont->UID, &psf->uid))
  110.         continue;
  111.         if (!psf->font) {
  112.         /*
  113.          * Identity of UIDs is supposed to guarantee that the
  114.          * fonts have the same outlines and metrics.
  115.          */
  116.         *psame = FONT_SAME_OUTLINES | FONT_SAME_METRICS;
  117.         return i;
  118.         }
  119.     }
  120.     if (psf->font) {
  121.         int same = *psame =
  122.         bfont->procs.same_font((const gs_font *)bfont, psf->font,
  123.                        mask);
  124.  
  125.         if (same & FONT_SAME_OUTLINES)
  126.         return i;
  127.     }
  128.     }
  129.     *psame = 0;
  130.     return -1;
  131. }
  132.  
  133. /*
  134.  * We register the fonts in pdev->std_fonts so that the pointers can
  135.  * be weak (get set to 0 when the font is freed).
  136.  */
  137. private GS_NOTIFY_PROC(pdf_std_font_notify_proc);
  138. typedef struct pdf_std_font_notify_s {
  139.     gx_device_pdf *pdev;
  140.     int index;            /* in std_fonts */
  141.     gs_font *font;    /* for checking */
  142. } pdf_std_font_notify_t;
  143. gs_private_st_ptrs2(st_pdf_std_font_notify, pdf_std_font_notify_t,
  144.             "pdf_std_font_notify_t",
  145.             pdf_std_font_notify_enum_ptrs,
  146.             pdf_std_font_notify_reloc_ptrs,
  147.             pdev, font);
  148. private int
  149. pdf_std_font_notify_proc(void *vpsfn /*proc_data*/, void *event_data)
  150. {
  151.     pdf_std_font_notify_t *const psfn = vpsfn;
  152.     gx_device_pdf *const pdev = psfn->pdev;
  153.     gs_font *const font = psfn->font;
  154.  
  155.     if (event_data)
  156.     return 0;        /* unknown event */
  157.     if_debug4('_',
  158.           "[_]  notify 0x%lx: gs_font 0x%lx, id %ld, index=%d\n",
  159.           (ulong)psfn, (ulong)font, font->id, psfn->index);
  160. #ifdef DEBUG
  161.     if (pdev->std_fonts[psfn->index].font != font)
  162.     lprintf3("pdf_std_font_notify font = 0x%lx, std_fonts[%d] = 0x%lx\n",
  163.          (ulong)font, psfn->index,
  164.          (ulong)pdev->std_fonts[psfn->index].font);
  165.     else
  166. #endif
  167.     pdev->std_fonts[psfn->index].font = 0;
  168.     gs_font_notify_unregister(font, pdf_std_font_notify_proc, vpsfn);
  169.     gs_free_object(pdev->pdf_memory, vpsfn, "pdf_std_font_notify_proc");
  170.     return 0;
  171. }
  172.  
  173. /* Unregister the standard fonts when cleaning up. */
  174. private void
  175. pdf_std_font_unreg_proc(void *vpsfn /*proc_data*/)
  176. {
  177.     pdf_std_font_notify_proc(vpsfn, NULL);
  178. }
  179. void
  180. pdf_unregister_fonts(gx_device_pdf *pdev)
  181. {
  182.     int j;
  183.  
  184.     for (j = 0; j < PDF_NUM_STD_FONTS; ++j)
  185.     if (pdev->std_fonts[j].font != 0)
  186.         gs_notify_unregister_calling(&pdev->std_fonts[j].font->notify_list,
  187.                      pdf_std_font_notify_proc, NULL,
  188.                      pdf_std_font_unreg_proc);
  189. }
  190.  
  191. /*
  192.  * Scan a font directory for standard fonts.  Return true if any new ones
  193.  * were found.
  194.  */
  195. private bool
  196. scan_for_standard_fonts(gx_device_pdf *pdev, const gs_font_dir *dir)
  197. {
  198.     bool found = false;
  199.     gs_font *orig = dir->orig_fonts;
  200.  
  201.     for (; orig; orig = orig->next) {
  202.     gs_font_base *obfont;
  203.  
  204.     if (orig->FontType == ft_composite || !orig->is_resource)
  205.         continue;
  206.     obfont = (gs_font_base *)orig;
  207.     if (uid_is_UniqueID(&obfont->UID)) {
  208.         /* Is it one of the standard fonts? */
  209.         int i = pdf_find_standard_font(orig->key_name.chars,
  210.                        orig->key_name.size);
  211.  
  212.         if (i >= 0 && pdev->std_fonts[i].font == 0) {
  213.         pdf_std_font_notify_t *psfn =
  214.             gs_alloc_struct(pdev->pdf_memory, pdf_std_font_notify_t,
  215.                     &st_pdf_std_font_notify,
  216.                     "scan_for_standard_fonts");
  217.  
  218.         if (psfn == 0)
  219.             continue;    /* can't register */
  220.         psfn->pdev = pdev;
  221.         psfn->index = i;
  222.         psfn->font = orig;
  223.         if_debug4('_',
  224.               "[_]register 0x%lx: gs_font 0x%lx, id %ld, index=%d\n",
  225.               (ulong)psfn, (ulong)orig, orig->id, i);
  226.         gs_font_notify_register(orig, pdf_std_font_notify_proc, psfn);
  227.         pdev->std_fonts[i].uid = obfont->UID;
  228.         pdev->std_fonts[i].orig_matrix = obfont->FontMatrix;
  229.         pdev->std_fonts[i].font = orig;
  230.         found = true;
  231.         }
  232.     }
  233.     }
  234.     return found;
  235. }
  236.  
  237. /*
  238.  * Determine the embedding status of a font.  If the font is in the base
  239.  * 14, store its index (0..13) in *pindex, otherwise store -1 there.
  240.  */
  241. private bool
  242. font_is_symbolic(const gs_font *font)
  243. {
  244.     if (font->FontType == ft_composite)
  245.     return true;        /* arbitrary */
  246.     switch (((const gs_font_base *)font)->nearest_encoding_index) {
  247.     case ENCODING_INDEX_STANDARD:
  248.     case ENCODING_INDEX_ISOLATIN1:
  249.     case ENCODING_INDEX_WINANSI:
  250.     case ENCODING_INDEX_MACROMAN:
  251.     return false;
  252.     default:
  253.     return true;
  254.     }
  255. }
  256. private bool
  257. embed_list_includes(const gs_param_string_array *psa, const byte *chars,
  258.             uint size)
  259. {
  260.     uint i;
  261.  
  262.     for (i = 0; i < psa->size; ++i)
  263.     if (!bytes_compare(psa->data[i].data, psa->data[i].size, chars, size))
  264.         return true;
  265.     return false;
  266. }
  267. pdf_font_embed_t
  268. pdf_font_embed_status(gx_device_pdf *pdev, gs_font *font, int *pindex,
  269.               int *psame)
  270. {
  271.     const byte *chars = font->font_name.chars;
  272.     uint size = font->font_name.size;
  273.  
  274.     /*
  275.      * The behavior of Acrobat Distiller changed between 3.0 (PDF 1.2),
  276.      * which will never embed the base 14 fonts, and 4.0 (PDF 1.3), which
  277.      * doesn't treat them any differently from any other fonts.
  278.      */
  279. #if 0    /**************** DOESN'T WORK ****************/
  280.     if (pdev->CompatibilityLevel < 1.3) {
  281. #else
  282.     {
  283. #endif
  284.     /* Check whether the font is in the base 14. */
  285.     int index = pdf_find_standard_font(chars, size);
  286.  
  287.     if (index >= 0) {
  288.         *pindex = index;
  289.         if (font->is_resource) {
  290.         *psame = ~0;
  291.         return FONT_EMBED_STANDARD;
  292.         } else if (font->FontType != ft_composite &&
  293.                find_std_appearance(pdev, (gs_font_base *)font, -1,
  294.                        psame) == index)
  295.         return FONT_EMBED_STANDARD;
  296.     }
  297.     }
  298.     *pindex = -1;
  299.     *psame = 0;
  300.     /* Check the Embed lists. */
  301.     if (embed_list_includes(&pdev->params.NeverEmbed, chars, size))
  302.     return FONT_EMBED_NO;
  303.     if (pdev->params.EmbedAllFonts || font_is_symbolic(font) ||
  304.     embed_list_includes(&pdev->params.AlwaysEmbed, chars, size))
  305.     return FONT_EMBED_YES;
  306.     return FONT_EMBED_NO;
  307. }
  308.  
  309. /* ---------------- Everything else ---------------- */
  310.  
  311. /*
  312.  * Find the original (unscaled) standard font corresponding to an
  313.  * arbitrary font, if any.  Return its index in standard_fonts, or -1.
  314.  */
  315. int
  316. pdf_find_orig_font(gx_device_pdf *pdev, gs_font *font, gs_matrix *pfmat)
  317. {
  318.     bool scan = true;
  319.     int i;
  320.  
  321.     if (font->FontType == ft_composite)
  322.     return -1;
  323.     for (;; font = font->base) {
  324.     gs_font_base *bfont = (gs_font_base *)font;
  325.     int same;
  326.  
  327.     /* Look for a standard font with the same appearance. */
  328.     i = find_std_appearance(pdev, bfont, 0, &same);
  329.     if (i >= 0)
  330.         break;
  331.     if (scan) {
  332.         /* Scan for fonts with any of the standard names that */
  333.         /* have a UID. */
  334.         bool found = scan_for_standard_fonts(pdev, font->dir);
  335.  
  336.         scan = false;
  337.         if (found) {
  338.         i = find_std_appearance(pdev, bfont, 0, &same);
  339.         if (i >= 0)
  340.             break;
  341.         }
  342.     }
  343.     if (font->base == font)
  344.         return -1;
  345.     }
  346.     *pfmat = pdev->std_fonts[i].orig_matrix;
  347.     return i;
  348. }
  349.  
  350. /*
  351.  * Allocate a font resource.  If descriptor_id is gs_no_id, no
  352.  * FontDescriptor is allocated.
  353.  */
  354. int
  355. pdf_alloc_font(gx_device_pdf *pdev, gs_id rid, pdf_font_t **ppfres,
  356.            const pdf_font_descriptor_t *pfd_in)
  357. {
  358.     gs_memory_t *mem = pdev->v_memory;
  359.     pdf_font_descriptor_t *pfd = 0;
  360.     gs_string chars_used, glyphs_used;
  361.     int code;
  362.     pdf_font_t *pfres;
  363.  
  364.     chars_used.data = 0;
  365.     glyphs_used.data = 0;
  366.     if (pfd_in != 0) {
  367.     code = pdf_alloc_resource(pdev, resourceFontDescriptor,
  368.                   pfd_in->rid, (pdf_resource_t **)&pfd, 0L);
  369.     if (code < 0)
  370.         return code;
  371.     chars_used.size = pfd_in->chars_used.size;
  372.     chars_used.data = gs_alloc_string(mem, chars_used.size,
  373.                       "pdf_alloc_font(chars_used)");
  374.     if (chars_used.data == 0)
  375.         goto fail;
  376.     memset(chars_used.data, 0, chars_used.size);
  377.     pfd->values = pfd_in->values;
  378.     pfd->chars_used = chars_used;
  379.     pfd->glyphs_used = glyphs_used;
  380.     pfd->subset_ok = true;
  381.     pfd->FontFile_id = 0;
  382.     pfd->base_font = 0;
  383.     pfd->notified = false;
  384.     pfd->written = false;
  385.     }
  386.     code = pdf_alloc_resource(pdev, resourceFont, rid,
  387.                   (pdf_resource_t **)ppfres, 0L);
  388.     if (code < 0)
  389.     goto fail;
  390.     pfres = *ppfres;
  391.     memset((byte *)pfres + sizeof(pdf_resource_t), 0,
  392.        sizeof(*pfres) - sizeof(pdf_resource_t));
  393.     sprintf(pfres->frname, "R%ld", pfres->object->id);
  394.     pfres->index = -1;
  395.     pfres->is_MM_instance = false;
  396.     pfres->BaseEncoding = ENCODING_INDEX_UNKNOWN;
  397.     pfres->Differences = 0;
  398.     pfres->FontDescriptor = pfd;
  399.     pfres->write_Widths = false;
  400.     pfres->char_procs = 0;
  401.     pfres->skip = false;
  402.     return 0;
  403.  fail:
  404.     if (glyphs_used.data)
  405.     gs_free_string(mem, glyphs_used.data, glyphs_used.size,
  406.                "pdf_alloc_font(glyphs_used)");
  407.     if (chars_used.data)
  408.     gs_free_string(mem, chars_used.data, chars_used.size,
  409.                "pdf_alloc_font(chars_used)");
  410.     gs_free_object(mem, pfd, "pdf_alloc_font(descriptor)");
  411.     return code;
  412. }
  413.  
  414. /*
  415.  * Determine whether a font is a subset font by examining the name.
  416.  */
  417. bool
  418. pdf_has_subset_prefix(const byte *str, uint size)
  419. {
  420.     int i;
  421.  
  422.     if (size < SUBSET_PREFIX_SIZE || str[SUBSET_PREFIX_SIZE - 1] != '+')
  423.     return false;
  424.     for (i = 0; i < SUBSET_PREFIX_SIZE - 1; ++i)
  425.     if ((uint)(str[i] - 'A') >= 26)
  426.         return false;
  427.     return true;
  428. }
  429.  
  430. /*
  431.  * Make the prefix for a subset font from the font's resource ID.
  432.  */
  433. void
  434. pdf_make_subset_prefix(byte *str, ulong id)
  435. {
  436.     int i;
  437.     ulong v;
  438.  
  439.     for (i = 0, v = id * 987654321; i < SUBSET_PREFIX_SIZE - 1; ++i, v /= 26)
  440.     str[i] = 'A' + (v % 26);
  441.     str[SUBSET_PREFIX_SIZE - 1] = '+';
  442. }
  443.  
  444. /*
  445.  * Adjust the FontName of a newly created FontDescriptor so that it is
  446.  * unique if necessary.
  447.  */
  448. int
  449. pdf_adjust_font_name(const gx_device_pdf *pdev, pdf_font_descriptor_t *pfd,
  450.              bool is_standard)
  451. {
  452.     int code = 0;
  453.  
  454.     if (MAKE_FONT_NAMES_UNIQUE) {
  455.     /* Check whether this name has already been used. */
  456.     int j = 0;
  457.     pdf_font_descriptor_t *old;
  458.     byte *chars = pfd->FontName.chars;
  459.     uint size = pfd->FontName.size;
  460.  
  461. #define SUFFIX_CHAR '~'
  462.     /*
  463.      * If the name looks as though it has one of our unique suffixes,
  464.      * remove the suffix.
  465.      */
  466.     {
  467.         int i;
  468.  
  469.         for (i = size;
  470.          i > 0 && isxdigit(chars[i - 1]);
  471.          --i)
  472.         DO_NOTHING;
  473.         if (i < size && i > 0 && chars[i - 1] == SUFFIX_CHAR) {
  474.         do {
  475.             --i;
  476.         } while (i > 0 && chars[i - 1] == SUFFIX_CHAR);
  477.         size = i + 1;
  478.         }
  479.         code = size != pfd->FontName.size;
  480.     }
  481.     /*
  482.      * Non-standard fonts with standard names must always use a suffix
  483.      * to avoid being confused with the standard fonts.
  484.      */
  485.     if (!is_standard)
  486.         for (; j < NUM_RESOURCE_CHAINS; ++j)
  487.         for (old = (pdf_font_descriptor_t *)pdev->resources[resourceFontDescriptor].chains[j];
  488.              old != 0; old = old->next
  489.              ) {
  490.             const byte *old_chars = old->FontName.chars;
  491.             uint old_size = old->FontName.size;
  492.  
  493.             if (old == pfd)
  494.             continue;
  495.             if (pdf_has_subset_prefix(old_chars, old_size))
  496.             old_chars += SUBSET_PREFIX_SIZE,
  497.                 old_size -= SUBSET_PREFIX_SIZE;
  498.             if (!bytes_compare(old_chars, old_size, chars, size))
  499.             goto found;
  500.         }
  501.     found:
  502.     if (j < NUM_RESOURCE_CHAINS) {
  503.         /* Create a unique name. */
  504.         char suffix[sizeof(long) * 2 + 2];
  505.         uint suffix_size;
  506.  
  507.         sprintf(suffix, "%c%lx", SUFFIX_CHAR,
  508.             pdf_resource_id((pdf_resource_t *)pfd));
  509.         suffix_size = strlen(suffix);
  510.         if (size + suffix_size > sizeof(pfd->FontName.chars))
  511.         return_error(gs_error_rangecheck);
  512.         memcpy(chars + size, (const byte *)suffix, suffix_size);
  513.         size += suffix_size;
  514.         code = 1;
  515.     }
  516.     pfd->FontName.size = size;
  517. #undef SUFFIX_CHAR
  518.     }
  519.     return code;
  520. }
  521.  
  522. /* Add an encoding difference to a font. */
  523. int
  524. pdf_add_encoding_difference(gx_device_pdf *pdev, pdf_font_t *ppf, int chr,
  525.                 const gs_font_base *bfont, gs_glyph glyph)
  526. {
  527.     pdf_encoding_element_t *pdiff = ppf->Differences;
  528.  
  529.     if (pdiff == 0) {
  530.     pdiff = gs_alloc_struct_array(pdev->pdf_memory, 256,
  531.                       pdf_encoding_element_t,
  532.                       &st_pdf_encoding_element,
  533.                       "Differences");
  534.     if (pdiff == 0)
  535.         return_error(gs_error_VMerror);
  536.     memset(pdiff, 0, sizeof(pdf_encoding_element_t) * 256);
  537.     ppf->Differences = pdiff;
  538.     }
  539.     pdiff[chr].glyph = glyph;
  540.     pdiff[chr].str.data = (const byte *)
  541.     bfont->procs.callbacks.glyph_name(glyph, &pdiff[chr].str.size);
  542.     return 0;
  543. }
  544.  
  545. /* Get the width of a given character in a (base) font. */
  546. int
  547. pdf_char_width(pdf_font_t *ppf, int ch, gs_font *font,
  548.            int *pwidth /* may be NULL */)
  549. {
  550.     if (ch < 0 || ch > 255)
  551.     return_error(gs_error_rangecheck);
  552.     if (!(ppf->widths_known[ch >> 3] & (1 << (ch & 7)))) {
  553.     gs_font_base *bfont = (gs_font_base *)font;
  554.     gs_glyph glyph = bfont->procs.encode_char(font, (gs_char)ch,
  555.                           GLYPH_SPACE_INDEX);
  556.     int wmode = font->WMode;
  557.     gs_glyph_info_t info;
  558.     double w, v;
  559.     int code;
  560.  
  561.     if (glyph != gs_no_glyph &&
  562.         (code = font->procs.glyph_info(font, glyph, NULL,
  563.                        GLYPH_INFO_WIDTH0 << wmode,
  564.                        &info)) >= 0
  565.         ) {
  566.         gs_const_string gnstr;
  567.  
  568.         if (wmode && (w = info.width[wmode].y) != 0)
  569.         v = info.width[wmode].x;
  570.         else
  571.         w = info.width[wmode].x, v = info.width[wmode].y;
  572.         if (v != 0)
  573.         return_error(gs_error_rangecheck);
  574.         if (font->FontType == ft_TrueType) {
  575.         /* TrueType fonts have 1 unit per em, we want 1000. */
  576.         w *= 1000;
  577.         }
  578.         ppf->Widths[ch] = (int)w;
  579.         /*
  580.          * If the character is .notdef, don't mark the width as known,
  581.          * just in case this is an incrementally defined font.
  582.          */
  583.         gnstr.data = (const byte *)
  584.         bfont->procs.callbacks.glyph_name(glyph, &gnstr.size);
  585.         if (gnstr.size != 7 || memcmp(gnstr.data, ".notdef", 7))
  586.         ppf->widths_known[ch >> 3] |= 1 << (ch & 7);
  587.     } else {
  588.         /* Try for MissingWidth. */
  589.         static const gs_point tt_scale = {1000, 1000};
  590.         const gs_point *pscale = 0;
  591.         gs_font_info_t finfo;
  592.  
  593.         if (font->FontType == ft_TrueType) {
  594.         /* TrueType fonts have 1 unit per em, we want 1000. */
  595.         pscale = &tt_scale;
  596.         }
  597.         code = font->procs.font_info(font, pscale, FONT_INFO_MISSING_WIDTH,
  598.                      &finfo);
  599.         if (code < 0)
  600.         return code;
  601.         ppf->Widths[ch] = finfo.MissingWidth;
  602.         /*
  603.          * Don't mark the width as known, just in case this is an
  604.          * incrementally defined font.
  605.          */
  606.     }
  607.     }
  608.     if (pwidth)
  609.     *pwidth = ppf->Widths[ch];
  610.     return 0;
  611. }
  612.  
  613. /*
  614.  * Find the range of character codes that includes all the defined
  615.  * characters in a font.  This is a separate procedure only for
  616.  * readability: it is only called from one place in pdf_update_text_state.
  617.  */
  618. void
  619. pdf_find_char_range(gs_font *font, int *pfirst, int *plast)
  620. {
  621.     gs_glyph notdef = gs_no_glyph;
  622.     int first = 0, last = 255;
  623.     gs_glyph glyph;
  624.  
  625.     switch (font->FontType) {
  626.     case ft_encrypted:
  627.     case ft_encrypted2: {
  628.     /* Scan the Encoding vector looking for .notdef. */
  629.     gs_font_base *const bfont = (gs_font_base *)font;
  630.     int ch;
  631.  
  632.     for (ch = 0; ch <= 255; ++ch) {
  633.         gs_glyph glyph =
  634.         font->procs.encode_char(font, (gs_char)ch,
  635.                     GLYPH_SPACE_INDEX);
  636.         gs_const_string gnstr;
  637.  
  638.         if (glyph == gs_no_glyph)
  639.         continue;
  640.         gnstr.data = (const byte *)
  641.         bfont->procs.callbacks.glyph_name(glyph, &gnstr.size);
  642.         if (gnstr.size == 7 && !memcmp(gnstr.data, ".notdef", 7)) {
  643.         notdef = glyph;
  644.         break;
  645.         }
  646.     }
  647.     break;
  648.     }
  649.     default:
  650.     DO_NOTHING;
  651.     }
  652.     while (last >= first &&
  653.        ((glyph =
  654.          font->procs.encode_char(font, (gs_char)last,
  655.                      GLYPH_SPACE_INDEX))== gs_no_glyph ||
  656.         glyph == notdef || glyph == gs_min_cid_glyph)
  657.        )
  658.     --last;
  659.     while (first <= last &&
  660.        ((glyph =
  661.          font->procs.encode_char(font, (gs_char)first,
  662.                      GLYPH_SPACE_INDEX))== gs_no_glyph ||
  663.         glyph == notdef || glyph == gs_min_cid_glyph)
  664.        )
  665.     ++first;
  666.     if (first > last)
  667.     last = first;    /* no characters used */
  668.     *pfirst = first;
  669.     *plast = last;
  670. }
  671.  
  672. /* Compute the FontDescriptor.values for a font. */
  673. private int
  674. font_char_bbox(gs_rect *pbox, gs_glyph *pglyph, gs_font *font, int ch,
  675.            const gs_matrix *pmat)
  676. {
  677.     gs_glyph glyph;
  678.     gs_glyph_info_t info;
  679.     int code;
  680.  
  681.     glyph = font->procs.encode_char(font, (gs_char)ch, GLYPH_SPACE_INDEX);
  682.     if (glyph == gs_no_glyph)
  683.     return gs_error_undefined;
  684.     code = font->procs.glyph_info(font, glyph, pmat, GLYPH_INFO_BBOX, &info);
  685.     if (code < 0)
  686.     return code;
  687.     *pbox = info.bbox;
  688.     if (pglyph)
  689.     *pglyph = glyph;
  690.     return 0;
  691. }
  692. int
  693. pdf_compute_font_descriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd,
  694.                 gs_font *font, const byte *used /*[32]*/)
  695. {
  696.     gs_font_base *bfont = (gs_font_base *)font;
  697.     gs_glyph glyph, notdef;
  698.     int index;
  699.     int wmode = font->WMode;
  700.     int members = (GLYPH_INFO_WIDTH0 << wmode) |
  701.     GLYPH_INFO_BBOX | GLYPH_INFO_NUM_PIECES;
  702.     gs_glyph letters[52];
  703.     int num_letters = 0;
  704.     pdf_font_descriptor_values_t desc;
  705.     gs_matrix smat;
  706.     gs_matrix *pmat = NULL;
  707.     int fixed_width = 0;
  708.     int small_descent = 0, small_height = 0;
  709.     int code;
  710.  
  711.     memset(&desc, 0, sizeof(desc));
  712.     desc.FontType = font->FontType;
  713.     desc.FontBBox.p.x = desc.FontBBox.p.y = max_int;
  714.     desc.FontBBox.q.x = desc.FontBBox.q.y = min_int;
  715.     /*
  716.      * Embedded TrueType fonts use a 1000-unit character space, but the
  717.      * font itself uses a 1-unit space.  Compensate for this here.
  718.      */
  719.     if (font->FontType == ft_TrueType) {
  720.     gs_make_scaling(1000.0, 1000.0, &smat);
  721.     pmat = &smat;
  722.     }
  723.     /*
  724.      * See the note on FONT_IS_ADOBE_ROMAN / FONT_USES_STANDARD_ENCODING
  725.      * in gdevpdff.h for why the following substitution is made.
  726.      */
  727. #if 0
  728. #  define CONSIDER_FONT_SYMBOLIC(font) font_is_symbolic(font)
  729. #else
  730. #  define CONSIDER_FONT_SYMBOLIC(font)\
  731.   ((font)->FontType == ft_composite ||\
  732.    ((const gs_font_base *)(font))->encoding_index != ENCODING_INDEX_STANDARD)
  733. #endif
  734.     if (CONSIDER_FONT_SYMBOLIC(font))
  735.     desc.Flags |= FONT_IS_SYMBOLIC;
  736.     else {
  737.     /*
  738.      * Look at various specific characters to guess at the remaining
  739.      * descriptor values (CapHeight, ItalicAngle, StemV, XHeight,
  740.      * and flags SERIF, SCRIPT, ITALIC, ALL_CAPS, and SMALL_CAPS).
  741.      * The algorithms are pretty crude.
  742.      */
  743.     /*
  744.      * Look at the glyphs for the lower-case letters.  If they are
  745.      * all missing, this is an all-cap font; if any is present, check
  746.      * the relative heights to determine whether this is a small-cap font.
  747.      */
  748.     bool small_present = false;
  749.     int ch;
  750.     int x_height = min_int;
  751.     int cap_height = 0;
  752.     gs_rect bbox, bbox2;
  753.  
  754.     desc.Flags |= FONT_IS_ADOBE_ROMAN; /* required if not symbolic */
  755.     for (ch = 'a'; ch <= 'z'; ++ch) {
  756.         int y0, y1;
  757.  
  758.         code =
  759.         font_char_bbox(&bbox, &letters[num_letters], font, ch, pmat);
  760.         if (code < 0)
  761.         continue;
  762.         ++num_letters;
  763.         rect_merge(desc.FontBBox, bbox);
  764.         small_present = true;
  765.         y0 = (int)bbox.p.y;
  766.         y1 = (int)bbox.q.y;
  767.         switch (ch) {
  768.         case 'b': case 'd': case 'f': case 'h':
  769.         case 'k': case 'l': case 't': /* ascender */
  770.         small_height = max(small_height, y1);
  771.         case 'i':        /* anomalous ascent */
  772.         break;
  773.         case 'j':        /* descender with anomalous ascent */
  774.         small_descent = min(small_descent, y0);
  775.         break;
  776.         case 'g': case 'p': case 'q': case 'y': /* descender */
  777.         small_descent = min(small_descent, y0);
  778.         default:        /* no ascender or descender */
  779.         x_height = max(x_height, y1);        
  780.         }
  781.     }
  782.     desc.XHeight = (int)x_height;
  783.     if (!small_present)
  784.         desc.Flags |= FONT_IS_ALL_CAPS;
  785.     for (ch = 'A'; ch <= 'Z'; ++ch) {
  786.         code =
  787.         font_char_bbox(&bbox, &letters[num_letters], font, ch, pmat);
  788.         if (code < 0)
  789.         continue;
  790.         ++num_letters;
  791.         rect_merge(desc.FontBBox, bbox);
  792.         cap_height = max(cap_height, (int)bbox.q.y);
  793.     }
  794.     desc.CapHeight = cap_height;
  795.     /*
  796.      * Look at various glyphs to determine ItalicAngle, StemV,
  797.      * SERIF, SCRIPT, and ITALIC.
  798.      */
  799.     if ((code = font_char_bbox(&bbox, NULL, font, ':', pmat)) >= 0 &&
  800.         (code = font_char_bbox(&bbox2, NULL, font, '.', pmat)) >= 0
  801.         ) {
  802.         /* Calculate the dominant angle. */
  803.         int angle = 
  804.         (int)(atan2((bbox.q.y - bbox.p.y) - (bbox2.q.y - bbox2.p.y),
  805.                 (bbox.q.x - bbox.p.x) - (bbox2.q.x - bbox2.p.x)) *
  806.               radians_to_degrees) - 90;
  807.  
  808.         /* Normalize to [-90..90]. */
  809.         while (angle > 90)
  810.         angle -= 180;
  811.         while (angle < -90)
  812.         angle += 180;
  813.         if (angle < -30)
  814.         angle = -30;
  815.         else if (angle > 30)
  816.         angle = 30;
  817.         /*
  818.          * For script or embellished fonts, we can get an angle that is
  819.          * slightly off from zero even for non-italic fonts.
  820.          * Compensate for this now.
  821.          */
  822.         if (angle <= 2 && angle >= -2)
  823.         angle = 0;
  824.         desc.ItalicAngle = angle;
  825.     }
  826.     if (desc.ItalicAngle)
  827.         desc.Flags |= FONT_IS_ITALIC;
  828.     if (code >= 0) {
  829.         double wdot = bbox2.q.x - bbox2.p.x;
  830.  
  831.         if ((code = font_char_bbox(&bbox2, NULL, font, 'I', pmat)) >= 0) {
  832.         double wcolon = bbox.q.x - bbox.p.x;
  833.         double wI = bbox2.q.x - bbox2.p.x;
  834.  
  835.         desc.StemV = (int)wdot;
  836.         if (wI > wcolon * 2.5 || wI > (bbox2.q.y - bbox2.p.y) * 0.25)
  837.             desc.Flags |= FONT_IS_SERIF;
  838.         }
  839.     }
  840.     }
  841.     /*
  842.      * Scan the entire glyph space to compute Ascent, Descent, FontBBox,
  843.      * and the fixed width if any.  Avoid computing the bounding box of
  844.      * letters a second time.
  845.      */
  846.     num_letters = psf_sort_glyphs(letters, num_letters);
  847.     desc.Ascent = desc.FontBBox.q.y;
  848.     notdef = gs_no_glyph;
  849.     for (index = 0;
  850.      (code = font->procs.enumerate_glyph(font, &index, GLYPH_SPACE_INDEX, &glyph)) >= 0 &&
  851.          index != 0;
  852.      ) {
  853.     gs_glyph_info_t info;
  854.     gs_const_string gnstr;
  855.  
  856.     if (psf_sorted_glyphs_include(letters, num_letters, glyph)) {
  857.         /* We don't need the bounding box. */
  858.         code = font->procs.glyph_info(font, glyph, pmat,
  859.                       members - GLYPH_INFO_BBOX, &info);
  860.         if (code < 0)
  861.         return code;
  862.     } else {
  863.         code = font->procs.glyph_info(font, glyph, pmat, members, &info);
  864.         if (code < 0)
  865.         return code;
  866.         rect_merge(desc.FontBBox, info.bbox);
  867.         if (!info.num_pieces)
  868.         desc.Ascent = max(desc.Ascent, info.bbox.q.y);
  869.     }
  870.     if (notdef == gs_no_glyph) {
  871.         gnstr.data = (const byte *)
  872.         bfont->procs.callbacks.glyph_name(glyph, &gnstr.size);
  873.         if (gnstr.size == 7 && !memcmp(gnstr.data, ".notdef", 7)) {
  874.         notdef = glyph;
  875.         desc.MissingWidth = info.width[wmode].x;
  876.         }
  877.     }
  878.     if (info.width[wmode].y != 0)
  879.         fixed_width = min_int;
  880.     else if (fixed_width == 0)
  881.         fixed_width = info.width[wmode].x;
  882.     else if (info.width[wmode].x != fixed_width)
  883.         fixed_width = min_int;
  884.     }
  885.     if (code < 0)
  886.     return code;
  887.     if (desc.Ascent == 0)
  888.     desc.Ascent = desc.FontBBox.q.y;
  889.     desc.Descent = desc.FontBBox.p.y;
  890.     if (!(desc.Flags & (FONT_IS_SYMBOLIC | FONT_IS_ALL_CAPS)) &&
  891.     (small_descent > desc.Descent / 3 || desc.XHeight > small_height * 0.9)
  892.     )
  893.     desc.Flags |= FONT_IS_SMALL_CAPS;
  894.     if (fixed_width > 0) {
  895.     desc.Flags |= FONT_IS_FIXED_WIDTH;
  896.     desc.AvgWidth = desc.MaxWidth = desc.MissingWidth = fixed_width;
  897.     }
  898.     if (desc.CapHeight == 0)
  899.     desc.CapHeight = desc.Ascent;
  900.     if (desc.StemV == 0)
  901.     desc.StemV = (int)(desc.FontBBox.q.x * 0.15);
  902.     pfd->values = desc;
  903.     return 0;
  904. }
  905.